package ch.bfh.abcmmh.controller.operating.vehiclepool;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;

import org.apache.log4j.Logger;

import ch.bfh.abcmmh.controller.logging.TSLoggingFactory;
import ch.bfh.abcmmh.controller.operating.clock.Clock;
import ch.bfh.abcmmh.model.cars.Vehicle;
import ch.bfh.abcmmh.model.cars.specialVehicles.Bus;
import ch.bfh.abcmmh.model.cars.specialVehicles.Car;
import ch.bfh.abcmmh.model.cars.specialVehicles.Truck;
import ch.bfh.abcmmh.model.interfaces.IVehiclePool;
import ch.bfh.abcmmh.model.streetutils.street.Street;

public class VehiclePool extends Observable implements Observer, IVehiclePool {

	Logger logger = TSLoggingFactory.getFileLogger("street");

	protected ArrayList<Car> cars = new ArrayList<Car>();
	protected ArrayList<Bus> buses = new ArrayList<Bus>();
	protected ArrayList<Truck> trucks = new ArrayList<Truck>();

	protected int carNumber = 0;
	protected int defVehicleWidth;

	protected Street street;
	protected Street[] streets;
	protected int chance = 4;

	public VehiclePool(Street street) {
		this.street = street;
	}

	public VehiclePool(Street[] streets) {
		this.streets = streets;
	}

	@Override
	public void update(Observable o, Object arg) {

		removeAllofStreetVehicles();
		
		if (new Random().nextInt(chance) == 1) {

			int streetNumber = 1;
			if (streets.length > 1) {
				streetNumber = new Random().nextInt(streets.length);
			}

			if (firstStreetpartIsFree(streetNumber)) {
				Vehicle vehicle = carBusOrTruck(streetNumber);
				Clock clock = (Clock) o;
				clock.addObserver(vehicle);
				addVehicleToList(vehicle);
				setChanged();
				notifyObservers(vehicle);
				clearChanged();

			}
		}

		for (int i = streets.length - 1; i >= 0; i--) {
			logger.info(streets[i]);
		}
		logger.info("");
		logger.info("");

	}

	private boolean firstStreetpartIsFree(int streetnumber) {
		for (int i = 0; i < 40; i++) {
			if (!streets[streetnumber].getSAttribute(i).isFree()) {
				return false;
			}
		}

		return true;
	}

	private Vehicle carBusOrTruck(int streetNumber) {
		Random random = new Random();
		int rv = random.nextInt(10);

		if (rv < 1) {
			return new Bus(this.streets[streetNumber], 70, 0, 0, streetNumber);
		} else if (rv < 3) {
			return new Truck(this.streets[streetNumber], 70, 0, 0, streetNumber);
		}
		return new Car(this.streets[streetNumber], 70, 0, 0, streetNumber);
	}

	private void removeAllofStreetVehicles() {
		Car gone = null;
		for (Car c : cars) {
			if (!c.isOnStreet()) {
				gone = c;
				break;
			}
		}
		cars.remove(gone);
		Bus bgone = null;
		for (Bus b : buses) {
			if (!b.isOnStreet()) {
				bgone = b;
				break;
			}
		}
		buses.remove(bgone);
		Truck tgone = null;
		for (Truck t : trucks) {
			if (!t.isOnStreet()) {
				tgone = t;
				break;
			}
		}
		trucks.remove(tgone);
	}

	public boolean firstStreetElementfree() {
		return street.getSAttribute(0).isFree();
	}

	@Override
	public void putVehicleOnStreet(Vehicle vehicle) {

		this.addVehicleToList(vehicle);
	}

	private void addVehicleToList(Vehicle vehicle) {
		if (Car.class.isInstance(vehicle)) {
			cars.add((Car) vehicle);
		}
		if (Bus.class.isInstance(vehicle)) {
			buses.add((Bus) vehicle);
		}
		if (Truck.class.isInstance(vehicle)) {
			trucks.add((Truck) vehicle);
		}
	}

	@Override
	public ArrayList<Car> getAllCars() {
		return this.cars;
	}

	@Override
	public ArrayList<Bus> getAllBuses() {
		return this.buses;
	}

	@Override
	public ArrayList<Truck> getAllTrucks() {
		return this.trucks;
	}

	public int getChance() {
		return chance;
	}

	public void setChance(int chance) {
		this.chance = chance;
	}

	@Override
	public int getAverageSpeedofCars() {
		int totalspeed = 0;
		for (Car c : cars) {
			totalspeed += c.getSpeedinKM();
		}
		if (cars.size() != 0) {
			return totalspeed / cars.size();
		} else {
			return 0;
		}
	}

	@Override
	public int getAverageSpeedofBuses() {
		int totalspeed = 0;
		for (Bus b : buses) {
			totalspeed += b.getSpeedinKM();
		}
		if (buses.size() != 0) {
			return totalspeed / buses.size();
		} else {
			return 0;
		}
	}

	@Override
	public int getAverageSpeedofTrucks() {
		int totalspeed = 0;
		for (Truck t : trucks) {
			totalspeed += t.getSpeedinKM();
		}
		if (trucks.size() != 0) {
			return totalspeed / trucks.size();
		} else {
			return 0;
		}
	}

}
